import MarkdownIt from "markdown-it";
import Renderer from "markdown-it/lib/renderer";

function escapeHtml(html: string) {
  return html
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/\u00a0/g, " ");
}

var options = {
  beforeMath: "",
  afterMath: "",
  beforeInlineMath: "\\(",
  afterInlineMath: "\\)",
  beforeDisplayMath: "\\[",
  afterDisplayMath: "\\]",
};


export default function (md: MarkdownIt) {
  md.renderer.rules = Object.assign<Renderer.RenderRuleRecord, Renderer.RenderRuleRecord>(md.renderer.rules, {

    'inline_math': (tokens, idx) => {
      return options.beforeInlineMath + escapeHtml(tokens[idx].content) + options.afterInlineMath
    },
    'display_math': (tokens, idx) => {
      return options.beforeDisplayMath + escapeHtml(tokens[idx].content) + options.afterDisplayMath
    },
    math: (tokens, idx) => {
      return options.beforeMath + escapeHtml(tokens[idx].content) + options.afterMath
    },
  })

  md.inline.ruler.before("escape", "math", (state, silent) => {
    var startMathPos = state.pos;
    if (state.src.charCodeAt(startMathPos) !== 0x5c /* \ */) {
      return false;
    }
    var match = state.src
      .slice(++startMathPos)
      .match(/^(?:\\\[|\\\(|begin\{([^}]*)\})/);
    if (!match) {
      return false;
    }
    startMathPos += match[0].length;
    let type = ''
    let endMarker = ''
    let includeMarkers = false
    if (match[0] === "\\[") {
      type = "display_math";
      endMarker = "\\\\]";
    } else if (match[0] === "\\(") {
      type = "inline_math";
      endMarker = "\\\\)";
    } else if (match[1]) {
      type = "math";
      endMarker = "\\end{" + match[1] + "}";
      includeMarkers = true;
    }
    var endMarkerPos = state.src.indexOf(endMarker, startMathPos);
    if (endMarkerPos === -1) {
      return false;
    }
    var nextPos = endMarkerPos + endMarker.length;
    if (!silent) {
      var token = state.push(type, "", 0);
      token.content = includeMarkers
        ? state.src.slice(state.pos, nextPos)
        : state.src.slice(startMathPos, endMarkerPos);
    }
    state.pos = nextPos;
    return true;
  });

  md.inline.ruler.push("texMath", (state, silent) => {
    var startMathPos = state.pos;
    if (state.src.charCodeAt(startMathPos) !== 0x24 /* $ */) {
      return false;
    }

    // Parse tex math according to http://pandoc.org/README.html#math
    var endMarker = "$";
    var afterStartMarker = state.src.charCodeAt(++startMathPos);

    if (afterStartMarker === 0x24 /* $ */) {
      endMarker = "$$";

      if (state.src.charCodeAt(++startMathPos) === 0x24 /* $ */) {

        // 3 markers are too much
        return false;
      }
    } else {
      // Skip if opening $ is succeeded by a space character
      if (
        afterStartMarker === 0x20 /* space */ ||
        afterStartMarker === 0x09 /* \t */ ||
        afterStartMarker === 0x0a /* \n */
      ) {
        return false;
      }
    }
    var endMarkerPos = state.src.indexOf(endMarker, startMathPos);
    if (endMarkerPos === -1) {
      return false;
    }
    if (state.src.charCodeAt(endMarkerPos - 1) === 0x5c /* \ */) {
      return false;
    }
    // if (state.src.charCodeAt(endMarkerPos - 1) === 37 /* % */) {
    //   console.log(state.src.slice(startMathPos, endMarkerPos))
    //   return false
    // }
    var nextPos = endMarkerPos + endMarker.length;
    if (endMarker.length === 1) {
      // Skip if $ is preceded by a space character
      var beforeEndMarker = state.src.charCodeAt(endMarkerPos - 1);
      if (
        beforeEndMarker === 0x20 /* space */ ||
        beforeEndMarker === 0x09 /* \t */ ||
        beforeEndMarker === 0x0a /* \n */
      ) {
        return false;
      }

      // @XXX 修改一下
      // Skip if closing $ is succeeded by a digit (eg $5 $10 ...)
      var suffix = state.src.slice(nextPos).split(endMarker)
      // if (suffix >= 0x30 && suffix < 0x3a) {
      //   return false;
      // }
      if (suffix.length > 0) {
        return false
      }
    }
    console.log(silent)
    if (!silent) {
      var token = state.push(
        endMarker.length === 1 ? "inline_math" : "display_math",
        "",
        0
      );

      token.content = state.src.slice(startMathPos, endMarkerPos);
    }
    state.pos = nextPos;
    return true;
  });


};
